package com.jzy.bxb.app.server;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.mina.core.session.IoSession;
import org.apache.mina.http.HttpRequestImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jzy.bxb.app.timer.WeatherTimer;
import com.jzy.bxb.core.handler.HandlerEntity;
import com.jzy.bxb.core.handler.HttpCode;
import com.jzy.bxb.core.handler.IHandler;
import com.jzy.bxb.core.mina.HttpServer;
import com.jzy.bxb.core.mina.config.MinaServerConfig;
import com.jzy.bxb.core.mina.handler.HttpServerIoHandler;
import com.jzy.bxb.core.script.ScriptManager;
import com.jzy.bxb.core.server.Service;
import com.jzy.bxb.core.thread.ThreadType;
import com.jzy.bxb.core.util.FileUtil;

/**
 * http连接
 *
 * @author JiangZhiYong
 * @date 2017-03-31 QQ:359135103
 */
public class AppHttpServer extends Service<MinaServerConfig> {

	private static final Logger log = LoggerFactory.getLogger(AppHttpServer.class);

	private final HttpServer httpServer;
	private final MinaServerConfig minaServerConfig;

	public AppHttpServer(String configPath) {
		super();
		this.minaServerConfig = FileUtil.getConfigXML(configPath, "minaServerConfig_http.xml", MinaServerConfig.class);
		if (minaServerConfig == null) {
			System.exit(0);
			throw new RuntimeException(String.format("%s 配置文件minaServerConfig_http.xml 未找到", configPath));
		}
		this.httpServer = new HttpServer(minaServerConfig, new AppHttpServerHandler(this));
	}

	@Override
	protected void running() {
		log.debug(" run ... ");
		httpServer.run();
		//定时任务
		ScheduledExecutorService scheduledExecutorService=Executors.newScheduledThreadPool(3);
		getServerThreads().put(ThreadType.Schedule, scheduledExecutorService);
		scheduledExecutorService.scheduleAtFixedRate(new WeatherTimer(), 10, 2400, TimeUnit.SECONDS);
	}

	@Override
	protected void onShutdown() {
		super.onShutdown();
		log.debug(" stop ... ");
		httpServer.stop();
	}

	@Override
	public String toString() {
		return minaServerConfig.getName();
	}
}

/**
 * 消息处理器
 *
 * @author JiangZhiYong
 * @date 2017-03-31 QQ:359135103
 */
class AppHttpServerHandler extends HttpServerIoHandler {

	private static final Logger log = LoggerFactory.getLogger(AppHttpServerHandler.class);

	private Service<MinaServerConfig> service;

	public AppHttpServerHandler(Service<MinaServerConfig> service) {
		this.service = service;
	}

	@Override
	protected Service<MinaServerConfig> getSevice() {
		return this.service;
	}

	/**
	 * 从写父类，添加权限验证
	 */
	@Override
	public void messageReceived(IoSession ioSession, Object message) {
		if (!(message instanceof HttpRequestImpl)) {
			log.warn("HttpServerIoHandler:" + message.getClass().getName());
//			ioSession.closeNow();
			return;
		}
		long begin = System.currentTimeMillis();

		HttpRequestImpl httpRequest = (HttpRequestImpl) message;
		Class<? extends IHandler> handlerClass = ScriptManager.getInstance()
				.getHttpHandler(httpRequest.getRequestPath());
		HandlerEntity handlerEntity = ScriptManager.getInstance().getHttpHandlerEntity(httpRequest.getRequestPath());
		if (handlerClass == null) {
			handlerClass = ScriptManager.getInstance().getHttpHandler("");
			handlerEntity = ScriptManager.getInstance().getHttpHandlerEntity("");
		}
		if (handlerClass == null) {
			log.error("Http 容器 未能找到 content = {} 的 httpMessageBean tostring: {}", httpRequest.getRequestPath(),
					ioSession.getRemoteAddress().toString());
			return;
		}

		try {
			IHandler handler = handlerClass.newInstance();
			handler.setMessage(httpRequest);
			handler.setSession(ioSession);
			handler.setCreateTime(System.currentTimeMillis());
			
			if(handler instanceof AuthHttpHandler){
				AuthHttpHandler authHttpHandler=(AuthHttpHandler)handler;
				if(!authHttpHandler.auth()){
					authHttpHandler.sendMsg("登录超时，请重新登录",map->map.put("code", HttpCode.LOGIN_EXPIRE));
					return;
				}
				
			}
			log.info(httpRequest.toString());
			
			Executor executor = getSevice().getExecutor(handlerEntity.thread());
			if (executor != null) {
				executor.execute(handler);
			} else {
				handler.run();
			}

		} catch (InstantiationException | IllegalAccessException ex) {
			log.error("messageReceived build message error !!! ", ex);
		}

		long cost = System.currentTimeMillis() - begin;
		if (cost > 1000L) {
			log.warn("{}执行：{}ms",httpRequest.getRequestPath(),cost);
		}
	}

}
